﻿/***  File Header  ************************************************************/
/**
* @file P4th.h
*
* PICO FORTHインタープリタ
* @author shozo fukuda
* @date   作成 Tue Oct 11 19:52:00 2005
* @date   修正 $Date: 06/04/14 10:09 $
* System  Generic <br>
*
*******************************************************************************/
#ifndef _P4TH_H
#define _P4TH_H

/*******************************************************************************
* IMPORTS:
*******************************************************************************/
#include "charm.h"
#include "TxIO.h"

/*******************************************************************************
* CONSTANT:
*******************************************************************************/
#define EOL   '\n'
#define MAX_COUNTED_STRING  255

// iStateの状態
#define INTERPRET       0         // インタープリット
#define COMP_NAME       1         // コンパイル: 名前フェーズ
#define COMP_CODE       2         // コンパイル: CODEフェーズ
#define COMP_SELF       3         // セルフコンパイル
#define COMP_FINISH     INTERPRET // コンパイル完了

// ワードの属性
#define F_IMMEDIATE     0x8000

#define FCODE(x)        ((x) & 0x3FFF)
#define IsImmediate(x)  (mCode[x] & F_IMMEDIATE)

#define W2CFA(wd)       (wd + 2)

/*******************************************************************************
* TYPE:
*******************************************************************************/
typedef unsigned short  Code;
typedef long             Data;
typedef Code              Word;

// マジック変数
union Magic {
  Data D;
  Code C[2];
};

// P4th関数ポインタ
class P4th;
typedef void (*P4thFunc)(P4th*);

// P4th定数テーブル
struct P4thConst {
  long  mVal;
  char* mName;
};

/***  Class Header  ***********************************************************/
/**
* P4thインタープリタ・クラス
* @par 解説
*   P4thインタープリタ
**/
/**************************************************************************{{{*/
class P4th {
friend class P4thTest;

//CONSTANT:
public:
  enum {
    WORD_LENGTH   = 31,
    
    MAX_DSTACK    = 1024,     // データスタックサイズ
    MAX_RSTACK    = 1024,     // リターンスタックサイズ
    
    MAX_CODE      = 8*1024,   // コンパイル・コード領域サイズ
    MAX_EXAM      = 512,      // インタプリット用一時コード領域サイズ
    MAX_CODE_BUFF = MAX_CODE + MAX_EXAM,
    EXAM          = MAX_CODE,
    
    MAX_NAME_BUFF = 16*1024,  // 名前領域サイズ
    MAX_LINE      = 80,       // 

    MAX_BACK_TEXT = 80*7,     // 書き戻しバッファサイズ
    MAX_TAKE_TEXT = 80*3,     // 受け取りバッファサイズ
    MAX_TEXT_BUFF = MAX_BACK_TEXT + MAX_TAKE_TEXT,    //テキストバッファサイズ
    
    MAX_MSG_BUFF  = 80*3,     // 結果メッセージバッファサイズ
  };

protected:
  // 組み込みワードが定義された辞書
  static UCHAR*      _Name;       // 組み込みワードの名前定義
  static const long  _NameFence;  // 組み込みワードの名前領域サイズ
  static Code*       _Code;       // 組み込みワードのコード定義
  static const long  _CodeFence;  // 組み込みワードのコード領域サイズ
  static P4thFunc*   _Func;       // 関数テーブル
  static P4thConst** _Const;      // 定数テーブル

//LIFECYCLE:
public:
  static P4th* Instance(TxIO* io);

  P4th();

  void Reset();
  void AttachIO(TxIO* io);

//ACTION:
/* インタプリタ/コンパイラ・モジュール {{{*/
public:
  void REP();

  void Eval();

  void Build(Code pcode);
  void Here();
  long Offs(long loc);

  Code& Memory(long loc)
    { return mCode[loc]; }

  void BegSelf(); 
  void EndSelf(); 
  
  void Unknown();
  void Literal();

  void Colon(); 
  void Constant();
  void DoConst();
  void Variable();
  void DoVar();

protected:
  void Call(Code pcode)
    { iW = pcode + 1;
      _Func[mCode[pcode]&0x3FFF](this);
    }

    bool ConvNum(long& value);
/*}}}*/

/* リーダー・モジュール {{{*/
public:
  char* ReadLine();

  char Read();
  void PutBack(char c);
  int  ReadWord(UCHAR* cstr);
  
  void ToUpper(UCHAR* cstr);

  long MatchCStrStr(UCHAR* cstr, char* str, long i = 1);
  bool EqCStrStr(UCHAR* cstr, char* str);
  
  void Parse(int dlmt);
  void ParseWord(int dlmt);
/*}}}*/

/* 辞書モジュール {{{*/
public:
  Code Find(UCHAR* name);
  bool FindConst(long& value);
  Word Create();

  Word&  Next(Word wd)  { return mCode[wd]; }
  UCHAR* Name(Word wd)  { return &mName[mCode[wd+1]]; }
/*}}}*/
  
/* スタックマシン・モジュール {{{*/
public:
  // データスタックオペレーション
  void  Push(long value);
  long  Pop();
  void  Roll(long index);
  void  Reverse(long index);
  long& At(long index);
  void  Crush(long index);
  long  Depth();
  void  Clr();
  
  // リターンスタックオペレーション
  void  RPush(long value);
  long  RPop();
  long& RAt(long index);

  // デバッグツール
  void DumpNew();
/*}}}*/

/* プリントアウト・モジュール {{{*/
public:
  void PutC(char c);
  void PutS(char* s);
  void Printf(char* fmt, ...);
  void Version();
/*}}}*/

//ATTRIBUTE:
public:
  char* const iText;// 入力テキスト先頭ポインタ
  
  long iState;      // テキストインタプリタ状態フラグ
  long iCapital;    // 大文字固定フラグ

  long iCurrent;    // 辞書ボキャブラリ・ポインタ
  
  long iIP;         // 実行ポインタ
  long iW;          // ワークレジスタ

protected:
  // データスタック
  long mDSize;
  long mS[MAX_DSTACK];
  long mSP;
  
  long mCSP;        // コンパイル整合性チェック用スタックポインタ

  // リターンスタック
  long mRSize;
  long mRS[MAX_RSTACK];
  long mRP;

  // コード領域
  Code mCode[MAX_CODE_BUFF];
  long mDP;         // 空きコード領域ポインタ
  long mDPX;        // インタプリット時のポインタ一時退避用
  
  // 名前領域
  UCHAR mName[MAX_NAME_BUFF];
  UCHAR mSym[MAX_LINE];
  long  mNP;        // 空き名前領域ポインタ
  long  mNPX;       // インタプリット時のポインタ一時退避用

  // 入力テキストバッファ
  char  mTextBuff[MAX_TEXT_BUFF];
  char* mCP;        // 次に読み取る文字を指すカーソル
  
  // 出力バッファ
  char  mMessage[MAX_MSG_BUFF];
  
  // 入出力チャネル
  TxIO* mIO;
};

/*INLINE METHOD:
--$-----------------------------------*/
inline void P4th::AttachIO(TxIO* io)
{ mIO = io; }

inline void P4th::Build(Code pcode)
{ mCode[mDP++] = pcode; }

inline void P4th::Here()
{ Push(mDP); }

inline long P4th::Offs(long loc)
{ return (mDP - loc); }

/*******************************************************************************
* REGULAR C-FUNCTION:
*******************************************************************************/

/*******************************************************************************
* GLOBAL VARIABLE:
*******************************************************************************/

#endif /* _P4TH_H */
